export default class StepGuide {
  constructor(options) {
    const defaults = {
      steps: [],
      maskColor: 'rgba(0, 0, 0, 0.6)',
      btnNextText: '下一步',
      btnPrevText: '上一步',
      btnSkipText: '跳过',
      btnFinishText: '完成',
      padding: 15,
      maxWidth: 300,
      position: 'auto',
      scrollLock: true,
      zIndex: 10000
    };

    this.config = { ...defaults, ...options };
    this.currentStep = null;
    this.targetElement = null;
    this.initDom();
  }

  /* 初始化DOM结构 */
  initDom() {
    // 遮罩层
    this.mask = this.createMask();
    // 高亮框
    this.highlightBox = null;
    // 提示框
    this.tooltip = this.createTooltip();
    
    document.body.append(this.mask, this.tooltip);
    this.bindEvents();
  }

  createMask() {
    const mask = document.createElement('div');
    this.applyStyles(mask, {
      position: 'fixed',
      top: 0,
      left: 0,
      width: '100vw',
      height: '100vh',
      zIndex: this.config.zIndex - 10, // 比提示框低10级
      display: 'none'
    });
    return mask;
  }

  createTooltip() {
    const tooltip = document.createElement('div');
    this.applyStyles(tooltip, {
      position: 'fixed',
      zIndex: this.config.zIndex,
      background: '#fff',
      padding: '20px',
      borderRadius: '8px',
      maxWidth: `${this.config.maxWidth}px`,
      display: 'none',
      boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
      transition: 'opacity 0.2s, transform 0.2s',
      pointerEvents: 'auto', // 允许操作按钮交互
      top:0
    });
    return tooltip;
  }

  /* 事件绑定 */
  bindEvents() {
    // 按钮事件委托
    this.tooltip.addEventListener('click', (e) => {
      const btn = e.target.closest('button');
      if (!btn) return;

      if (btn.classList.contains('btn-next')) this.next();
      if (btn.classList.contains('btn-prev')) this.previous();
      if (btn.classList.contains('btn-skip')) this.destroy();
    });

    // 动态定位监听
    window.addEventListener('scroll', this.updatePosition, true);
    window.addEventListener('resize', this.updatePosition);
  }

  /* 核心：启动引导 */
  start() {
    if (this.config.steps.length === 0) {
      console.error('[StepGuide] 未定义引导步骤');
      return;
    }
    
    if (this.config.scrollLock) {
      document.body.style.overflow = 'hidden';
    }
    
    this.currentStep = 0;
    this.showStep(this.currentStep);
  }

  /* 显示指定步骤 */
  showStep(stepIndex) {
    this.cleanup();
    const step = this.config.steps[stepIndex];
    if (!step) return;

    this.targetElement = document.querySelector(step.element);
    if (!this.validateTarget()) return;

    this.createHighlightBox();
    this.updateTooltipContent(step);
    this.updatePosition();
    this.showElements();
  }

  /* 验证目标元素 */
  validateTarget() {
    if (!this.targetElement) {
      console.warn(`[StepGuide] 元素未找到: ${this.config.steps[this.currentStep].element}`);
      this.next();
      return false;
    }
    
    // 确保元素可见
    if (this.targetElement.offsetParent === null) {
      console.warn(`[StepGuide] 元素不可见: ${this.targetElement}`);
      return false;
    }
    
    return true;
  }

  /* 创建高亮框 */
  createHighlightBox() {
    this.highlightBox = document.createElement('div');
    this.applyStyles(this.highlightBox, {
      position: 'absolute',
      zIndex: this.config.zIndex - 5,
      pointerEvents: 'none',
      boxShadow: `0 0 0 9999px ${this.config.maskColor}`,
      transition: 'all 0.3s'
    });

    // 监听目标元素变化
    this.observer = new ResizeObserver(() => this.updatePosition());
    this.observer.observe(this.targetElement);
    document.body.appendChild(this.highlightBox);
  }

  /* 更新提示框内容 */
  updateTooltipContent(step) {
    this.tooltip.innerHTML = `
      <div class="guide-content">
        ${step.title ? `<h3 style="margin:0 0 12px;font-size:16px;">${step.title}</h3>` : ''}
        <div style="line-height:1.5;color:#666;">${step.content}</div>
        <div style="margin-top:20px;display:flex;justify-content:space-between;align-items:center">
          ${this.createNavigationButtons()}
        </div>
      </div>
    `;
  }

  createNavigationButtons() {
    return `
      <div>
        ${this.currentStep > 0 ? `
          <button class="btn-prev" style="margin-right:8px">
            ${this.config.btnPrevText}
          </button>` : ''}
        <button class="btn-skip">
          ${this.config.btnSkipText}
        </button>
      </div>
      <button class="btn-next">
        ${this.currentStep === this.config.steps.length - 1 
          ? this.config.btnFinishText 
          : this.config.btnNextText}
      </button>
    `;
  }

  /* 动态定位核心方法 */
  updatePosition = () => {
    if (!this.targetElement || !this.highlightBox) return;

    // 获取目标元素位置
    const targetRect = this.targetElement.getBoundingClientRect();
    const scrollX = window.scrollX || window.pageXOffset;
    const scrollY = window.scrollY || window.pageYOffset;

    // 更新高亮框位置
    this.applyStyles(this.highlightBox, {
      left: `${targetRect.left + scrollX}px`,
      top: `${targetRect.top + scrollY}px`,
      width: `${targetRect.width}px`,
      height: `${targetRect.height}px`
    });

    // 计算提示框位置
    const position = this.calculateTooltipPosition(targetRect);
    this.applyStyles(this.tooltip, {
      transform: `translate(${position.x}px, ${position.y}px)`,
      opacity: 1
    });
  };

  /* 智能定位算法 */
  calculateTooltipPosition(targetRect) {
    const padding = this.config.padding;
    const tooltipWidth = this.tooltip.offsetWidth;
    const tooltipHeight = this.tooltip.offsetHeight;

    // 可用空间计算
    const viewport = {
      width: window.innerWidth,
      height: window.innerHeight
    };

    // 候选位置数据
    const positions = {
      bottom: {
        x: targetRect.left,
        y: targetRect.bottom + padding,
        space: viewport.height - targetRect.bottom - padding,
        overflow: (y) => y + tooltipHeight > viewport.height
      },
      top: {
        x: targetRect.left,
        y: targetRect.top - padding - tooltipHeight,
        space: targetRect.top - padding,
        overflow: (y) => y < 0
      },
      right: {
        x: targetRect.right + padding,
        y: targetRect.top,
        space: viewport.width - targetRect.right - padding,
        overflow: (x) => x + tooltipWidth > viewport.width
      },
      left: {
        x: targetRect.left - padding - tooltipWidth,
        y: targetRect.top,
        space: targetRect.left - padding,
        overflow: (x) => x < 0
      }
    };

    // 自动选择位置
    let bestPosition = 'bottom';
    if (this.config.position === 'auto') {
      bestPosition = Object.entries(positions)
        .sort((a, b) => b[1].space - a[1].space)
        .find(([_, pos]) => pos.space > (pos.x ? tooltipWidth : tooltipHeight))?.[0] || 'bottom';
    } else {
      bestPosition = this.config.position;
    }

    // 边界修正
    let { x, y } = positions[bestPosition];
    x = Math.max(padding, Math.min(x, viewport.width - tooltipWidth - padding));
    y = Math.max(padding, Math.min(y, viewport.height - tooltipHeight - padding));

    return { x, y };
  }

  /* 显示元素 */
  showElements() {
    this.mask.style.display = 'block';
    this.tooltip.style.display = 'block';
    // 初始动画
    requestAnimationFrame(() => {
      this.tooltip.style.opacity = 1;
      this.tooltip.style.transform += ' scale(1)';
    });
  }

  /* 清理资源 */
  cleanup() {
    if (this.highlightBox) {
      this.observer?.disconnect();
      this.highlightBox.remove();
      this.highlightBox = null;
    }
    this.tooltip.style.opacity = 0;
  }

  destroy() {
    this.cleanup();
    this.mask.remove();
    // this.tooltip.remove();
    window.removeEventListener('scroll', this.updatePosition);
    window.removeEventListener('resize', this.updatePosition);
    document.body.style.overflow = '';
  }

  /* 工具方法 */
  applyStyles(element, styles) {
    Object.assign(element.style, styles);
  }

  next() {
    if (this.currentStep < this.config.steps.length - 1) {
      this.currentStep++;
      this.showStep(this.currentStep);
    } else {
      this.destroy();
    }
  }

  previous() {
    if (this.currentStep > 0) {
      this.currentStep--;
      this.showStep(this.currentStep);
    }
  }
}